package org.xxpay.pay.channel.recpay;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xxpay.core.common.util.AmountUtil;
import org.xxpay.core.common.util.MyBase64;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.AlipayPayOrder;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.ctrl.common.BaseController;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;

/**
 * @Description: 红包通道跳转
 * @author xxpay
 * @date 2019-02-13
 */
@Controller
public class RecpayController extends BaseController {

	private static final MyLog _log = MyLog.getLog(RecpayController.class);

	/**
	 * 转到前端收银台界面
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping("/api/"+ RecpayConfig.CHANNEL_NAME+"/pay_{type}.htm")
	public String toPay(HttpServletRequest request, ModelMap model, @PathVariable("type") String type) {
		JSONObject po = getJsonParam(request);
		String amount = getString(po, "amount");
		String payOrderId = getString(po, "payOrderId");
		String mchOrderNo = getString(po, "mchOrderNo");
		Boolean autoJump = getBoolean(po, "autoJump");
		// 订单创建时间与当前时间差值(此处使用db计算，为了避免服务器和db时间有差异)
		Long expireTime = commonService.payOrderService.getOrderTimeLeft(payOrderId, RecpayConfig.PAY_ORDER_TIME_OUT);
		if(expireTime == null || expireTime < 0) expireTime = 0l;
		String codeUrl = getString(po, "codeUrl");
		String codeImgUrl = getString(po, "codeImgUrl");
		model.put("amount", AmountUtil.convertCent2Dollar(amount));
		model.put("amountStr", "￥"+ AmountUtil.convertCent2Dollar(amount));
		model.put("mchOrderNo", mchOrderNo);
		model.put("payOrderId", payOrderId);
		model.put("expireTime", expireTime);
		model.put("codeUrl", codeUrl);
		model.put("codeImgUrl", codeImgUrl);
		model.put("autoJump", autoJump);
		return "payment/"+ RecpayConfig.CHANNEL_NAME+"/pay_" + type;
	}

	/**
	 * 查询订单payOrder
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping("/api/"+ RecpayConfig.CHANNEL_NAME+"/query")
	@ResponseBody
	public String toQuery(HttpServletRequest request) {
		JSONObject po = getJsonParam(request);
		String payOrderId = getString(po, "payOrderId");
		_log.info("[查询订单]参数payOrderId={}", payOrderId);

		PayOrder payOrder = commonService.payOrderService.findByPayOrderId(payOrderId);
		JSONObject retObj = new JSONObject();
		String status = "-1";
		String url = "";
		if(payOrder != null) {
			status = payOrder.getStatus() + "";
			url = payOrder.getReturnUrl();
		}
		retObj.put("status", status);
		retObj.put("url", url);
		_log.info("[查询订单]结果payOrderId={},retObj={}", payOrderId, retObj);
		return retObj.toJSONString();
	}

	/**
	 * 查询订单alipayPayOrder
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping("/api/"+ RecpayConfig.CHANNEL_NAME+"/getAliPayOrder")
	@ResponseBody
	public String getAliPayOrder(HttpServletRequest request) {
		JSONObject po = getJsonParam(request);
		String payOrderId = getString(po, "payOrderId");
		_log.info("[查询订单]参数payOrderId={}", payOrderId);

		AlipayPayOrder payOrder = commonService.alipayPayOrderService.findByPayOrderId(payOrderId);
		JSONObject retObj = new JSONObject();
		String status = "-1";
		String tradeNo = "";
		if(payOrder != null) {
			status = payOrder.getStatus() + "";
			if (("2").equals(status)){
				tradeNo = payOrder.getTradeNo();
			}
		}
		retObj.put("status", status);
		retObj.put("tradeNo", tradeNo);
		_log.info("[查询订单]结果payOrderId={},retObj={}", payOrderId, retObj);
		return retObj.toJSONString();
	}

	/**
	 * 支付宝红包收款界面
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping("/api/" + RecpayConfig.CHANNEL_NAME + "/alipay_red.htm")
	public String alipayRed(HttpServletRequest request, ModelMap model) throws ServletException, IOException {
		JSONObject po = getJsonParam(request);
		String alipayUserId = getString(po, "alipayUserId");
		String alipayAccount = getString(po, "alipayAccount");
		String amount = getString(po, "amount");
		String payOrderId = getString(po, "payOrderId");
		model.put("amount", amount);
		model.put("tradeNo", payOrderId);
		model.put("alipayUserId", alipayUserId);
		model.put("alipayAccount", alipayAccount);
		model.put("alipayName", "");
		return "payment/" + RecpayConfig.CHANNEL_NAME + "/alipay_red";
	}

	/**
	 * 支付宝口令收款界面
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping("/api/" + RecpayConfig.CHANNEL_NAME + "/alipay_rec_{param}.htm")
	public String alipayRec(HttpServletRequest request, ModelMap model, @PathVariable String param) {
		String paramJson = new String(MyBase64.decode(param));
		JSONObject po = JSONObject.parseObject(paramJson);
		String alipayUserId = getString(po, "alipayUserId");
		String alipayAccount = getString(po, "alipayAccount");
		String amount = getString(po, "amount");
		String payOrderId = getString(po, "payOrderId");
		String outUserId = request.getParameter("userId");
		if(outUserId == null) {
			model.put("errMsg","授权不成功，请重新下单");
			return "payment/" + RecpayConfig.CHANNEL_NAME + "/alipay_rec";
		}

		// 先根据payOrderId去查询，如果没有插入，有直接返回
		AlipayPayOrder alipayPayOrder = commonService.alipayPayOrderService.findByPayOrderId(payOrderId);
		if(alipayPayOrder != null) {
			Long createTime = alipayPayOrder.getCreateTime().getTime();
			Long nowTime = System.currentTimeMillis();
			Long timeDif = nowTime - createTime;
			if ( timeDif > RecpayConfig.PAY_ORDER_TIME_OUT * 1000){
				model.put("errMsg","订单超时，请重新下单");
				return "payment/" + RecpayConfig.CHANNEL_NAME + "/alipay_rec";
			}
			if(!outUserId.equals(alipayPayOrder.getOutUserId())) {
				model.put("errMsg","订单已存在，请重新下单");
				return "payment/" + RecpayConfig.CHANNEL_NAME + "/alipay_rec";
			}
			model.put("amount", amount);
			model.put("tradeNo", alipayPayOrder.getTradeNo());
			model.put("payOrderId", payOrderId);
			model.put("alipayUserId", alipayUserId);
			model.put("alipayAccount", alipayAccount);
			model.put("alipayName", "");
			return "payment/" + RecpayConfig.CHANNEL_NAME + "/alipay_rec";
		}

		alipayPayOrder = new AlipayPayOrder();
		alipayPayOrder.setPayOrderId(payOrderId);
		alipayPayOrder.setOutUserId(outUserId);
		alipayPayOrder.setAlipayAccount(alipayAccount);
		alipayPayOrder.setAmount(Long.parseLong(AmountUtil.convertDollar2Cent(amount)));
		alipayPayOrder.setStatus((byte) 1);
		alipayPayOrder.setInUserId(alipayUserId);
		int count = commonService.alipayPayOrderService.createAlipayPayOrder(alipayPayOrder);
		if(count != 1) {
			model.put("errMsg","支付人数过多，请重新下单");
			return "payment/" + RecpayConfig.CHANNEL_NAME + "/alipay_rec";
		}

		model.put("amount", amount);
		model.put("payOrderId", payOrderId);
		model.put("alipayUserId", alipayUserId);
		model.put("alipayAccount", alipayAccount);
		model.put("alipayName", "");
		return "payment/" + RecpayConfig.CHANNEL_NAME + "/alipay_rec";
	}

	/**
	 * APP查询未同步订单，返回五分钟内时间最早的
	 * @param request
	 * @return
	 */
	@RequestMapping("/api/recpay/get_trade")
	@ResponseBody
	public String queryAlipayPayOrderIng(HttpServletRequest request) {
		JSONObject param = getJsonParam(request);
		JSONObject resObj = new JSONObject();
		String inUserId = getString(param, "user_id");	// 支付宝收款用户ID
		_log.info("[APP查询支付宝订单]请求参数: user_id={}", inUserId);
		if(StringUtils.isBlank(inUserId)) {
			resObj.put("data", "null");
			_log.info("[APP查询支付宝订单]user_id={},返回:{}", inUserId, resObj);
			return resObj.toJSONString();
		}
		AlipayPayOrder alipayPayOrder = new AlipayPayOrder();
		alipayPayOrder.setInUserId(inUserId);
		alipayPayOrder.setStatus((byte) 1);	// 状态是待分配
		Date createTimeStart = new Date(System.currentTimeMillis() - (RecpayConfig.PAY_ORDER_TIME_OUT) * 1000);
		AlipayPayOrder order = commonService.alipayPayOrderService.find(alipayPayOrder, createTimeStart, null);
		if(order == null) {
			resObj.put("data", "null");
			_log.info("[APP查询支付宝订单]user_id={},返回:{}", inUserId, resObj);
			return resObj.toJSONString();
		}
		// 更新appHeartTime
		AlipayPayOrder updateAlipayPayOrder = new AlipayPayOrder();
		updateAlipayPayOrder.setPayOrderId(order.getPayOrderId());
		updateAlipayPayOrder.setAppHeartTime(new Date());
		commonService.alipayPayOrderService.update(updateAlipayPayOrder);
		// 返回数据
		JSONObject dataObj = new JSONObject();
		dataObj.put("payuid", order.getOutUserId());	// 付款用户ID
		dataObj.put("amount", AmountUtil.convertCent2Dollar(order.getAmount()+""));
		dataObj.put("remark", order.getPayOrderId());
		dataObj.put("order_id", order.getPayOrderId());
		dataObj.put("pay_type", "2");	// 2为AA收款
		resObj.put("data", dataObj);
		_log.info("[APP查询支付宝订单]user_id={},返回:{}", inUserId, resObj);
		return resObj.toJSONString();
	}

	/**
	 * APP设置单号和状态
	 * @param request
	 * @return
	 */
	@RequestMapping("/api/recpay/set_trade")
	@ResponseBody
	public String setTradeNo(HttpServletRequest request) {
		JSONObject param = getJsonParam(request);
		String payOrderId = getString(param, "orderid");
		String tradeNo = getString(param, "alipay_orderid");
		String appMsg = getString(param, "alipay_msg");
		_log.info("[APP设置支付宝订单]请求参数payOrderId={},tradeNo={},appMsg={}", payOrderId, tradeNo, appMsg);

		AlipayPayOrder alipayPayOrder = new AlipayPayOrder();
		alipayPayOrder.setPayOrderId(payOrderId);
		alipayPayOrder.setSyncTime(new Date());
		alipayPayOrder.setAppMsg(appMsg != null ? appMsg.substring(0, Math.min(512, appMsg.length())) : "");
		if(tradeNo == null || "1".equals(tradeNo) ) {

		}else if("".equals(tradeNo)) {
			alipayPayOrder.setTradeNo(tradeNo);
			alipayPayOrder.setStatus((byte) 3);	// 订单生成失败
		}else {
			alipayPayOrder.setTradeNo(tradeNo);
			alipayPayOrder.setStatus((byte) 2);	// 已分配
		}
		int count = commonService.alipayPayOrderService.update(alipayPayOrder);
		_log.info("[APP设置支付宝订单]payOrderId={},tradeNo={},result={}", payOrderId, tradeNo, count);
		return "success";
	}

}
